<template>
  <div class="chart-container">
    <div class="toolbar">
      <el-button-group>
        <el-button size="small" @click="refreshData">
          <i class="el-icon-refresh"></i> 刷新
        </el-button>
        <el-button size="small" @click="fitView">
          <i class="el-icon-full-screen"></i> 适应视图
        </el-button>
        <el-button size="small" @click="resetZoom">
          <i class="el-icon-zoom-out"></i> 重置缩放
        </el-button>
      </el-button-group>

      <el-button-group style="margin-left: 10px;">
        <el-button
          size="small"
          :type="layoutType === 'force' ? 'primary' : ''"
          @click="switchLayout('force')"
        >
          <i class="el-icon-connection"></i> 力导向
        </el-button>
        <el-button
          size="small"
          :type="layoutType === 'organized' ? 'primary' : ''"
          @click="switchLayout('organized')"
        >
          <i class="el-icon-s-grid"></i> 整齐排列
        </el-button>
      </el-button-group>

      <el-dropdown @command="handleExport" style="margin-left: 10px;">
        <el-button size="small">
          <i class="el-icon-download"></i> 导出 <i class="el-icon-arrow-down el-icon--right"></i>
        </el-button>
        <el-dropdown-menu slot="dropdown">
          <el-dropdown-item command="png">导出为PNG</el-dropdown-item>
          <el-dropdown-item command="jpg">导出为JPG</el-dropdown-item>
          <el-dropdown-item command="svg">导出为SVG</el-dropdown-item>
        </el-dropdown-menu>
      </el-dropdown>
    </div>
    <div ref="chart" class="chart" v-loading="loading"></div>

    <!-- 右键菜单 -->
    <div
      v-show="contextMenu.visible"
      class="context-menu"
      :style="{ left: contextMenu.x + 'px', top: contextMenu.y + 'px' }"
      @click.stop
    >
      <div v-if="contextMenu.type === 'node'" class="menu-items">
        <div class="menu-item" @click="editNodeFromMenu">
          <i class="el-icon-edit"></i> 编辑节点
        </div>
        <div class="menu-item" @click="deleteNodeFromMenu">
          <i class="el-icon-delete"></i> 删除节点
        </div>
        <div class="menu-item" @click="addRelationFromNode">
          <i class="el-icon-connection"></i> 添加关系
        </div>
      </div>
      <div v-else-if="contextMenu.type === 'edge'" class="menu-items">
        <div class="menu-item" @click="editRelationFromMenu">
          <i class="el-icon-edit"></i> 编辑关系
        </div>
        <div class="menu-item" @click="deleteRelationFromMenu">
          <i class="el-icon-delete"></i> 删除关系
        </div>
      </div>
      <div v-else-if="contextMenu.type === 'canvas'" class="menu-items">
        <div class="menu-item" @click="addNodeFromCanvas">
          <i class="el-icon-plus"></i> 添加节点
        </div>
      </div>
    </div>
  </div>
</template>

<script>
import * as echarts from 'echarts'
import { chainAPI } from '@/api'

export default {
  name: 'IndustrialChainChart',
  props: {
    chartId: {
      type: [Number, String],
      required: false
    },
    chartName: {
      type: String,
      default: '产业链关系图'
    }
  },
  data() {
    return {
      chart: null,
      loading: false,
      layoutType: 'force', // 'force' 或 'organized'
      chartData: {
        nodes: [],
        edges: []
      },
      contextMenu: {
        visible: false,
        x: 0,
        y: 0,
        type: null,
        data: null
      }
    }
  },
  watch: {
    chartId: {
      handler(newChartId, oldChartId) {
        if (newChartId && newChartId !== oldChartId) {
          console.log('Chart ID changed from', oldChartId, 'to', newChartId)
          this.loadData()
        }
      },
      immediate: false
    }
  },
  mounted() {
    // 恢复保存的布局类型
    const savedLayoutType = localStorage.getItem('chartLayoutType')
    if (savedLayoutType && ['force', 'organized'].includes(savedLayoutType)) {
      this.layoutType = savedLayoutType
    }

    this.initChart()
    this.loadData()
    document.addEventListener('click', this.hideContextMenu)
  },
  beforeDestroy() {
    if (this.chart) {
      this.chart.dispose()
    }
    document.removeEventListener('click', this.hideContextMenu)
  },
  methods: {
    initChart() {
      this.chart = echarts.init(this.$refs.chart)

      // 节点点击事件
      this.chart.on('click', (params) => {
        if (params.dataType === 'node') {
          this.onNodeClick(params.data)
        } else if (params.dataType === 'edge') {
          this.onEdgeClick(params.data)
        }
      })

      // 节点右键事件
      this.chart.on('contextmenu', (params) => {
        params.event.event.preventDefault()
        this.showContextMenu(params.event.event, params.dataType, params.data)
      })

      // 节点双击事件
      this.chart.on('dblclick', (params) => {
        if (params.dataType === 'node') {
          this.onNodeDoubleClick(params.data)
        }
      })

      // 画布右键事件（空白区域）
      this.chart.getDom().addEventListener('contextmenu', (event) => {
        // 检查是否点击的是空白区域
        const params = this.chart.getZr().handler.findHover(event.offsetX, event.offsetY)
        if (!params.target) {
          event.preventDefault()
          this.showContextMenu(event, 'canvas', null)
        }
      })

      window.addEventListener('resize', () => {
        this.chart.resize()
      })
    },

    async loadData() {
      if (!this.chartId) {
        console.log('Chart ID is not available yet')
        return
      }

      this.loading = true
      try {
        const response = await chainAPI.getChainData(this.chartId)
        if (response.code === 200) {
          this.chartData = response.data
          this.updateChart()
        } else {
          this.$message.error('数据加载失败: ' + response.message)
        }
      } catch (error) {
        console.error('Load data error:', error)
        this.$message.error('网络请求失败')
      } finally {
        this.loading = false
      }
    },

    updateChart() {
      let processedNodes = this.chartData.nodes

      // 如果是整齐排列模式，重新计算节点位置
      if (this.layoutType === 'organized') {
        processedNodes = this.calculateOrganizedLayout(this.chartData.nodes, this.chartData.edges)
      }

      const nodes = processedNodes.map(node => ({
        id: node.id,
        name: node.name,
        x: this.layoutType === 'organized' ? node.x : (node.x || Math.random() * 800),
        y: this.layoutType === 'organized' ? node.y : (node.y || Math.random() * 600),
        symbolSize: node.size || 50,
        symbol: 'circle',
        itemStyle: {
          color: node.color || '#409EFF'
        },
        label: {
          show: true,
          formatter: (params) => {
            const firstChar = node.name ? node.name.charAt(0) : ''
            const fullName = node.name || ''
            return `{a|${firstChar}}\n{b|${fullName}}`
          },
          rich: {
            a: {
              fontSize: Math.max(12, (node.size || 50) * 0.3),
              color: '#fff',
              fontWeight: 'bold',
              align: 'center'
            },
            b: {
              fontSize: 10,
              color: '#333',
              align: 'center',
              padding: [5, 0, 0, 0]
            }
          }
        },
        emphasis: {
          label: {
            show: true,
            formatter: (params) => {
              const firstChar = node.name ? node.name.charAt(0) : ''
              const fullName = node.name || ''
              return `{a|${firstChar}}\n{b|${fullName}}`
            },
            rich: {
              a: {
                fontSize: Math.max(14, (node.size || 50) * 0.35),
                color: '#fff',
                fontWeight: 'bold',
                align: 'center'
              },
              b: {
                fontSize: 12,
                color: '#333',
                align: 'center',
                padding: [5, 0, 0, 0],
                fontWeight: 'bold'
              }
            }
          }
        },
        category: node.type,
        draggable: this.layoutType !== 'organized'
      }))

      const links = this.chartData.edges.map(edge => ({
        source: edge.source.toString(),
        target: edge.target.toString(),
        label: {
          show: true,
          formatter: edge.label || edge.type,
          fontSize: this.layoutType === 'organized' ? 12 : 10,
          color: this.layoutType === 'organized' ? '#333' : undefined
        },
        lineStyle: {
          color: edge.color || '#67C23A',
          width: (edge.strength || 1) * (this.layoutType === 'organized' ? 2 : 3),
          type: this.layoutType === 'organized' ? 'solid' : undefined
        },
        symbol: ['none', 'arrow'],
        symbolSize: this.layoutType === 'organized' ? [0, 12] : [0, 15],
        edgeSymbol: ['none', 'arrow'],
        edgeSymbolSize: this.layoutType === 'organized' ? [0, 12] : [0, 15]
      }))

      const categories = [...new Set(this.chartData.nodes.map(node => node.type))].map(type => ({
        name: type
      }))

      const option = {
        title: {
          text: this.chartName,
          left: 'center',
          textStyle: {
            color: '#333',
            fontSize: 18
          }
        },
        tooltip: {
          trigger: 'item',
          formatter: (params) => {
            if (params.dataType === 'node') {
              const node = this.chartData.nodes.find(n => n.id == params.data.id)
              return `
                <strong>${node.name}</strong><br/>
                类型: ${node.type}<br/>
                描述: ${node.description || '无'}
              `
            } else if (params.dataType === 'edge') {
              const edge = this.chartData.edges.find(e =>
                e.source == params.data.source && e.target == params.data.target
              )
              return `
                关系: ${edge.label || edge.type}<br/>
                强度: ${edge.strength || 1}
              `
            }
            return params.name
          }
        },
        legend: {
          orient: 'vertical',
          left: 'left',
          data: categories.map(cat => cat.name)
        },
        series: [{
          type: 'graph',
          layout: this.layoutType === 'organized' ? 'none' : 'force',
          data: nodes,
          links: links,
          categories: categories,
          roam: true,
          focusNodeAdjacency: true,
          itemStyle: {
            borderColor: '#fff',
            borderWidth: this.layoutType === 'organized' ? 3 : 2,
            shadowBlur: this.layoutType === 'organized' ? 15 : 10,
            shadowColor: this.layoutType === 'organized' ? 'rgba(0, 0, 0, 0.2)' : 'rgba(0, 0, 0, 0.3)'
          },
          label: {
            show: true,
            position: 'inside',
            fontSize: this.layoutType === 'organized' ? 12 : undefined
          },
          emphasis: {
            focus: 'adjacency',
            itemStyle: {
              borderWidth: this.layoutType === 'organized' ? 4 : 3
            }
          },
          edgeLabel: {
            fontSize: this.layoutType === 'organized' ? 12 : 10,
            color: this.layoutType === 'organized' ? '#333' : undefined
          },
          lineStyle: {
            color: 'source',
            curveness: this.layoutType === 'organized' ? 0 : 0.1,
            opacity: this.layoutType === 'organized' ? 0.8 : 1
          },
          force: this.layoutType === 'organized' ? undefined : {
            repulsion: 2000,
            gravity: 0.2,
            edgeLength: [50, 200],
            layoutAnimation: true
          }
        }]
      }

      this.chart.setOption(option, true)
    },

    onNodeClick(nodeData) {
      const node = this.chartData.nodes.find(n => n.id == nodeData.id)
      this.$emit('node-click', node)
    },

    onEdgeClick(edgeData) {
      const edge = this.chartData.edges.find(e =>
        e.source == edgeData.source && e.target == edgeData.target
      )
      this.$emit('edge-click', edge)
      this.$message.info(`点击了关系: ${edge.label || edge.type}`)
    },

    onNodeRightClick(nodeData, event) {
      const node = this.chartData.nodes.find(n => n.id == nodeData.id)
      this.$emit('node-right-click', { node, event })
    },

    onNodeDoubleClick(nodeData) {
      const node = this.chartData.nodes.find(n => n.id == nodeData.id)
      this.$emit('node-double-click', node)
    },

    refreshData() {
      this.loadData()
    },

    fitView() {
      this.chart.dispatchAction({
        type: 'restore'
      })
    },

    resetZoom() {
      this.chart.dispatchAction({
        type: 'restore'
      })
    },

    // 右键菜单相关方法
    showContextMenu(event, type, data) {
      this.hideContextMenu()
      this.contextMenu = {
        visible: true,
        x: event.clientX,
        y: event.clientY,
        type: type,
        data: data
      }
    },

    hideContextMenu() {
      this.contextMenu.visible = false
    },

    // 节点右键菜单操作
    editNodeFromMenu() {
      this.hideContextMenu()
      const node = this.chartData.nodes.find(n => n.id == this.contextMenu.data.id)
      this.$emit('edit-node', node)
    },

    deleteNodeFromMenu() {
      this.hideContextMenu()
      const node = this.chartData.nodes.find(n => n.id == this.contextMenu.data.id)
      this.$emit('delete-node', node)
    },

    addRelationFromNode() {
      this.hideContextMenu()
      const node = this.chartData.nodes.find(n => n.id == this.contextMenu.data.id)
      this.$emit('add-relation-from-node', node)
    },

    // 关系右键菜单操作
    editRelationFromMenu() {
      this.hideContextMenu()
      const edge = this.chartData.edges.find(e =>
        e.source == this.contextMenu.data.source && e.target == this.contextMenu.data.target
      )
      this.$emit('edit-relation', edge)
    },

    deleteRelationFromMenu() {
      this.hideContextMenu()
      const edge = this.chartData.edges.find(e =>
        e.source == this.contextMenu.data.source && e.target == this.contextMenu.data.target
      )
      this.$emit('delete-relation', edge)
    },

    // 画布右键菜单操作
    addNodeFromCanvas() {
      this.hideContextMenu()
      // 计算在图表中的位置
      const chartRect = this.chart.getDom().getBoundingClientRect()
      const x = this.contextMenu.x - chartRect.left
      const y = this.contextMenu.y - chartRect.top
      this.$emit('add-node-at-position', { x, y })
    },

    // 导出图片功能
    async handleExport(format) {
      if (!this.chart) {
        this.$message.error('图表未初始化')
        return
      }

      try {
        // 创建一个临时的更大的canvas来完整渲染图表
        await this.exportFullChart(format)
      } catch (error) {
        console.error('Export error:', error)
        this.$message.error('导出失败: ' + error.message)
      }
    },

    // 导出完整图表
    async exportFullChart(format) {
      const timestamp = new Date().toISOString().slice(0, 19).replace(/:/g, '-')
      const filename = `${this.chartName}_${timestamp}`

      // 计算所有节点的边界
      const nodes = this.chartData.nodes
      if (nodes.length === 0) {
        this.$message.warning('没有节点可导出')
        return
      }

      // 先让图表适应所有内容
      this.chart.dispatchAction({
        type: 'restore'
      })

      // 等待布局稳定
      await new Promise(resolve => setTimeout(resolve, 1000))

      // 获取当前图表的实际渲染位置
      const currentOption = this.chart.getOption()
      const seriesData = currentOption.series[0].data

      // 计算实际的节点位置边界
      let minX = Infinity, maxX = -Infinity, minY = Infinity, maxY = -Infinity
      let hasValidPositions = false

      seriesData.forEach(node => {
        // 获取节点在图表中的实际渲染位置
        let x, y

        if (node.x !== undefined && node.y !== undefined) {
          x = node.x
          y = node.y
          hasValidPositions = true
        } else if (node.value && Array.isArray(node.value) && node.value.length >= 2) {
          x = node.value[0]
          y = node.value[1]
          hasValidPositions = true
        } else {
          // 如果没有位置信息，使用默认布局
          x = Math.random() * 800
          y = Math.random() * 600
        }

        const size = (node.symbolSize || 50) / 2
        minX = Math.min(minX, x - size)
        maxX = Math.max(maxX, x + size)
        minY = Math.min(minY, y - size)
        maxY = Math.max(maxY, y + size)
      })

      // 如果没有有效位置，使用更大的默认尺寸
      if (!hasValidPositions) {
        minX = 0
        maxX = 1000
        minY = 0
        maxY = 800
      }

      // 计算导出尺寸，添加足够的边距
      const margin = 150
      const contentWidth = Math.max(maxX - minX, 800) + margin * 2
      const contentHeight = Math.max(maxY - minY, 600) + margin * 2

      // 设置导出尺寸，确保足够大
      const exportWidth = Math.max(contentWidth, 1600)
      const exportHeight = Math.max(contentHeight, 1200)

      // 创建临时容器
      const tempDiv = document.createElement('div')
      tempDiv.style.width = exportWidth + 'px'
      tempDiv.style.height = exportHeight + 'px'
      tempDiv.style.position = 'absolute'
      tempDiv.style.top = '-20000px'
      tempDiv.style.left = '-20000px'
      tempDiv.style.visibility = 'hidden'
      document.body.appendChild(tempDiv)

      try {
        const tempChart = echarts.init(tempDiv)

        // 创建导出专用的配置
        const exportOption = {
          title: {
            text: this.chartName,
            left: 'center',
            top: 20,
            textStyle: {
              color: '#333',
              fontSize: 24,
              fontWeight: 'bold'
            }
          },
          backgroundColor: '#fff',
          animation: false,
          series: [{
            type: 'graph',
            layout: 'none', // 使用固定布局，不让力导向重新计算
            data: seriesData.map(node => ({
              ...node,
              // 确保位置信息正确
              x: node.x !== undefined ? node.x : (node.value && node.value[0]) || Math.random() * 800,
              y: node.y !== undefined ? node.y : (node.value && node.value[1]) || Math.random() * 600,
              label: {
                show: true,
                position: 'inside',
                formatter: (params) => {
                  const originalNode = this.chartData.nodes.find(n => n.id == params.data.id)
                  const firstChar = originalNode?.name ? originalNode.name.charAt(0) : ''
                  const fullName = originalNode?.name || ''
                  return `{a|${firstChar}}\n{b|${fullName}}`
                },
                rich: {
                  a: {
                    fontSize: Math.max(14, (node.symbolSize || 50) * 0.35),
                    color: '#fff',
                    fontWeight: 'bold',
                    align: 'center'
                  },
                  b: {
                    fontSize: 12,
                    color: '#333',
                    align: 'center',
                    padding: [5, 0, 0, 0],
                    fontWeight: 'bold'
                  }
                }
              }
            })),
            links: currentOption.series[0].links || currentOption.series[0].edges || [],
            categories: currentOption.series[0].categories || [],
            roam: false, // 禁用缩放和平移
            focusNodeAdjacency: false,
            itemStyle: {
              borderColor: '#fff',
              borderWidth: 2,
              shadowBlur: 10,
              shadowColor: 'rgba(0, 0, 0, 0.3)'
            },
            lineStyle: {
              color: 'source',
              curveness: 0.1
            },
            edgeLabel: {
              fontSize: 12
            }
          }]
        }

        tempChart.setOption(exportOption)

        // 等待渲染完成
        await new Promise(resolve => setTimeout(resolve, 1000))

        let dataURL
        switch (format) {
          case 'png':
            dataURL = tempChart.getDataURL({
              type: 'png',
              pixelRatio: 3, // 提高分辨率
              backgroundColor: '#fff'
            })
            this.downloadImage(dataURL, `${filename}.png`)
            break
          case 'jpg':
            dataURL = tempChart.getDataURL({
              type: 'jpeg',
              pixelRatio: 3,
              backgroundColor: '#fff'
            })
            this.downloadImage(dataURL, `${filename}.jpg`)
            break
          case 'svg':
            const svgStr = tempChart.renderToSVGString()
            this.downloadSVG(svgStr, `${filename}.svg`)
            break
          default:
            this.$message.error('不支持的导出格式')
            return
        }

        tempChart.dispose()
        this.$message.success(`图表已导出为${format.toUpperCase()}格式`)

      } finally {
        document.body.removeChild(tempDiv)
      }
    },


    downloadImage(dataURL, filename) {
      const link = document.createElement('a')
      link.download = filename
      link.href = dataURL
      document.body.appendChild(link)
      link.click()
      document.body.removeChild(link)
    },

    downloadSVG(svgStr, filename) {
      const blob = new Blob([svgStr], { type: 'image/svg+xml' })
      const url = URL.createObjectURL(blob)
      const link = document.createElement('a')
      link.download = filename
      link.href = url
      document.body.appendChild(link)
      link.click()
      document.body.removeChild(link)
      URL.revokeObjectURL(url)
    },

    // 布局切换功能
    switchLayout(layoutType) {
      if (this.layoutType === layoutType) return

      this.layoutType = layoutType
      localStorage.setItem('chartLayoutType', layoutType)

      // 重新计算布局并更新图表
      this.updateChart()
    },

    // 计算整齐排列的布局
    calculateOrganizedLayout(nodes, edges) {
      // 按节点类型分组
      const typeGroups = {}
      nodes.forEach(node => {
        const type = node.type || 'default'
        if (!typeGroups[type]) {
          typeGroups[type] = []
        }
        typeGroups[type].push(node)
      })

      // 定义类型的排列顺序（产业链流程）
      const typeOrder = ['supplier', 'raw_material', 'component', 'manufacturer', 'contract_manufacturer', 'distributor', 'retailer', 'consumer']
      const availableTypes = Object.keys(typeGroups)

      // 按照产业链顺序排列类型
      const orderedTypes = typeOrder.filter(type => availableTypes.includes(type))
      // 添加未在预定义顺序中的类型
      availableTypes.forEach(type => {
        if (!orderedTypes.includes(type)) {
          orderedTypes.push(type)
        }
      })

      const result = []

      // 获取图表容器的实际尺寸
      const chartDom = this.$refs.chart
      const containerWidth = chartDom ? chartDom.clientWidth : 1200
      const containerHeight = chartDom ? chartDom.clientHeight : 800

      // 调整边距以适应实际容器
      const margin = Math.min(containerWidth, containerHeight) * 0.08 // 8% 的边距
      const availableWidth = containerWidth - margin * 2
      const availableHeight = containerHeight - margin * 2

      if (orderedTypes.length === 0) return result

      // 计算每列的宽度，确保有足够的间距避免重叠
      const minColumnWidth = 200 // 增加最小列宽
      const idealColumnWidth = availableWidth / orderedTypes.length
      const columnWidth = Math.max(minColumnWidth, idealColumnWidth)

      // 如果列太多，重新计算起始位置
      const totalUsedWidth = columnWidth * orderedTypes.length
      const startX = (containerWidth - totalUsedWidth) / 2 + columnWidth / 2

      orderedTypes.forEach((type, typeIndex) => {
        const nodesOfType = typeGroups[type]
        const columnX = startX + typeIndex * columnWidth

        if (nodesOfType.length === 1) {
          // 单个节点居中
          result.push({
            ...nodesOfType[0],
            x: columnX,
            y: containerHeight / 2
          })
        } else if (nodesOfType.length <= 3) {
          // 少数节点时垂直排列
          const nodeHeight = 100 // 增加节点占用高度
          const minSpacing = nodeHeight + 60 // 增加最小间距
          const maxSpacing = 180 // 增加最大间距

          const idealSpacing = availableHeight / (nodesOfType.length + 1)
          const actualSpacing = Math.max(minSpacing, Math.min(maxSpacing, idealSpacing))

          // 计算起始Y位置，使节点组在垂直方向居中
          const totalHeight = (nodesOfType.length - 1) * actualSpacing
          const startY = (containerHeight - totalHeight) / 2

          nodesOfType.forEach((node, nodeIndex) => {
            const y = startY + nodeIndex * actualSpacing

            // 少量节点时使用更大的水平偏移
            let offsetX = 0
            if (nodesOfType.length > 1) {
              offsetX = (nodeIndex % 2 === 0 ? -25 : 25)
            }

            result.push({
              ...node,
              x: columnX + offsetX,
              y: y
            })
          })
        } else {
          // 多个节点时使用网格布局避免重叠
          const nodesPerColumn = Math.ceil(Math.sqrt(nodesOfType.length)) // 计算每列节点数
          const subColumns = Math.ceil(nodesOfType.length / nodesPerColumn)

          const subColumnWidth = columnWidth * 0.8 / subColumns // 子列宽度
          const rowHeight = Math.min(120, availableHeight / (nodesPerColumn + 1)) // 行高

          // 起始位置偏移，使整个网格居中
          const gridStartX = columnX - (subColumnWidth * (subColumns - 1)) / 2
          const gridStartY = (containerHeight - (rowHeight * (nodesPerColumn - 1))) / 2

          nodesOfType.forEach((node, nodeIndex) => {
            const subColumnIndex = Math.floor(nodeIndex / nodesPerColumn)
            const rowIndex = nodeIndex % nodesPerColumn

            const x = gridStartX + subColumnIndex * subColumnWidth
            const y = gridStartY + rowIndex * rowHeight

            result.push({
              ...node,
              x: x,
              y: y
            })
          })
        }
      })

      return result
    }
  }
}
</script>

<style scoped>
.chart-container {
  width: 100%;
  height: 100%;
  position: relative;
}

.toolbar {
  position: absolute;
  top: 10px;
  right: 10px;
  z-index: 10;
  background: rgba(255, 255, 255, 0.9);
  padding: 8px;
  border-radius: 4px;
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
}

.chart {
  width: 100%;
  height: 100%;
}

.context-menu {
  position: fixed;
  z-index: 9999;
  background: white;
  border: 1px solid #e6e6e6;
  border-radius: 4px;
  box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
  padding: 4px 0;
  min-width: 120px;
}

.menu-items {
  list-style: none;
  margin: 0;
  padding: 0;
}

.menu-item {
  padding: 8px 16px;
  cursor: pointer;
  font-size: 14px;
  color: #606266;
  display: flex;
  align-items: center;
  transition: background-color 0.2s;
}

.menu-item:hover {
  background-color: #f5f7fa;
  color: #409eff;
}

.menu-item i {
  margin-right: 8px;
  width: 16px;
}
</style>